#pragma once

#include <iostream>
#include <memory>
#include <poll.h>
#include "Logger.hpp"
#include "Socket.hpp"
#include "InetAddr.hpp"

const static int gsize = sizeof(fd_set) * 8;
const static int gdefaultfd = -1;

class SelectServer
{
public:
    SelectServer(uint16_t port)
        : _listensocket(std::make_unique<TcpSocket>())
    {
        _listensocket->BuildlistenSocketMethod(port);
        for (int i = 0; i < gsize; i++)
        {
            fd_array[i] = gdefaultfd;
        }
        fd_array[0] = _listensocket->SockFd();
    }
    void Accept()
    {
        InetAddr clientadddr;
        int sockfd = _listensocket->Accept(&clientadddr);
        if (sockfd > 0)
        {
            int pos=0;
            for (; pos < gsize; pos++)
            {
                if (fd_array[pos] == gdefaultfd)
                {
                    fd_array[pos]=sockfd;
                    break;
                }
            }
            if(pos==gsize)
            {
                LOG(Loglevel::WARNING) << "server is full!";
                close(sockfd);
            }
        }
    }
    void Recver(int index)
    {
        int sockfd=fd_array[index];
        char buffer[1024];
        ssize_t n=recv(sockfd,buffer,sizeof(buffer)-1,0);
        if(n > 0)
        {
            buffer[n]=0;
            std::cout << "client say@ " << buffer << std::endl;
            std::string echo_string ="server echo# ";
            echo_string+=buffer;
            send(sockfd,echo_string.c_str(),echo_string.size(),0);
        }
        else if(n==0)
        {
            LOG(Loglevel::INFO) << "client quit, me too: " << fd_array[index];
            fd_array[index]=gdefaultfd;
            close(sockfd);
        }
        else
        { 
            LOG(Loglevel::INFO) << "recv error: " << fd_array[index];
            fd_array[index]=gdefaultfd;
            close(sockfd);
        }
    }
    void EventDispatcher(fd_set rfds)
    {
        LOG(Loglevel::INFO) << "fd就绪,有新事件到来";

        for (int i = 0; i < gsize; i++)
        {
            if (fd_array[i] == gdefaultfd)
                continue;

            if (FD_ISSET(fd_array[i], &rfds))
            {
                if (fd_array[i] == _listensocket->SockFd())
                {
                    Accept(); // 连接管理器
                }
                else
                {
                    Recver(i); // IO处理器
                }
            }
        }
    }
    void Run()
    {
        while (true)
        {
            struct timeval timeout = {0, 0}; // 阻塞
            fd_set rfds;
            FD_ZERO(&rfds);
            int maxfd = gdefaultfd;
            for (int i = 0; i < gsize; i++)
            {
                if (fd_array[i] == gdefaultfd)
                    continue;
                FD_SET(fd_array[i], &rfds);
                if (maxfd < fd_array[i])
                {
                    maxfd = fd_array[i];
                }
                LOG(Loglevel::DEBUG) << "添加fd: " << fd_array[i];
            }

            int n = select(maxfd + 1, &rfds, nullptr, nullptr, /*&timeout*/nullptr);
            switch (n)
            {
            case 0:
                LOG(Loglevel::DEBUG) << "timeouct...:" << timeout.tv_sec << ": " << timeout.tv_usec;
                break;
            case -1:
                LOG(Loglevel::ERROR) << "select error";
                break;
            default:
                EventDispatcher(rfds);
                break;
            }
        }
    }
    ~SelectServer()
    {
    }

private:
    std::unique_ptr<TcpSocket> _listensocket;
    int fd_array[gsize];
};